/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.solution;

import br.ufmg.dees.insane.util.IVector;

/**
 * @author jamile
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class CilindricalArcLengthControl extends ArcLengthControl {
    
    public CilindricalArcLengthControl() {
    }
	
	/**
	 * @param loadFactor
	 */
	public CilindricalArcLengthControl(double loadFactor) {
		super(loadFactor);
	}

	/* (non-Javadoc)
	 * @see br.ufmg.dees.insane.solution.IteractiveStrategy#getCorrector()
	 */
	public double getCorrector() {
		IVector aux = new IVector (step.getAssembler().getSizeOfXu());
		IVector incX1 = new IVector (step.getAssembler().getSizeOfXu());
		IVector incX2 = new IVector (step.getAssembler().getSizeOfXu());
		double a, b, c;
		double delta;
		double r1, r2;
		double theta1, theta2;
		double lr;
		double d1, d2;
		IVector xp = this.step.getXP();
		IVector unbalancedX = step.getUnbalancedX();
		aux.add(incX,step.getUnbalancedX());
		a = xp.dot(xp);
		b = 2 * aux.dot(xp);
		c = aux.dot(aux) - arcLength * arcLength;
		delta = b*b - 4*a*c;
		r1 = (-b + Math.sqrt(delta)) / (2*a);
		r2 = (-b - Math.sqrt(delta)) / (2*a);
		incX1.add(incX,unbalancedX);
		incX1.scaleAdd(r1, xp,incX1 );
		incX2.add(incX,unbalancedX);
		incX2.scaleAdd(r2, xp,incX2 );
		theta1 = incX1.dot(incX);
		theta2 = incX2.dot(incX);
		if(theta1 > 0.0 && theta2 < 0.0) lambda = r1;
		else if(theta1 < 0.0 && theta2 > 0.0) lambda = r2;
		else{
			lr = -c/b;
			d1 = Math.abs(r1 - lr);
			d2 = Math.abs(r2 - lr);
			if(d1 > d2) lambda = r2;
			else lambda = r1;
		}
		IVector aux2 = new IVector (step.getAssembler().getSizeOfXu());
		IVector aux3 = new IVector (step.getAssembler().getSizeOfXu());
		aux2.scale(lambda,xp);
		aux3.add(aux2, unbalancedX);
		incX.add(incX, aux3);
		return lambda;
	}

}
